package org.eclipseuseradmin.internal.ui;

import java.util.List;

import org.eclipse.core.runtime.IAdapterManager;
import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.ui.progress.DeferredTreeContentManager;
import org.eclipseuseradmin.ui.IRoleElement;
import org.eclipseuseradmin.ui.IRoleRootDescriptor;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.service.useradmin.Role;
import org.osgi.service.useradmin.UserAdmin;
import org.osgi.service.useradmin.UserAdminEvent;
import org.osgi.service.useradmin.UserAdminListener;

public class RolesContentProvider implements ITreeContentProvider,
		UserAdminListener {

	private TreeViewer viewer;

	private DeferredTreeContentManager contentManager = null;

	private UserAdmin userAdmin;

	private IAdapterManager adapterManager;

	public RolesContentProvider(TreeViewer viewer) {
		this.viewer = viewer;
		UserAdminUiPlugin.registerUserAdminListener(this);
	}

	public Object[] getChildren(Object parentElement) {

		if (parentElement instanceof RoleRootsRegistry) {
			return getChildren((RoleRootsRegistry) parentElement);
		}
		if (parentElement instanceof IRoleRootDescriptor) {
			return getChildren((RoleRootElement) parentElement);
		}

		IRoleElement roleElement = (IRoleElement) adapterManager.getAdapter(
				parentElement, IRoleElement.class);
		if (roleElement != null) {
			return getChildren(roleElement);
		}

		return new Object[0];

	}

	public boolean hasChildren(Object element) {
		if (element instanceof RoleRootsRegistry) {
			return true;
		}
		if (element instanceof RoleRootElement) {
			return true;
		}

		IRoleElement roleElement = (IRoleElement) adapterManager.getAdapter(
				element, IRoleElement.class);
		if (roleElement != null) {
			return roleElement.hasChildren();
		}

		return false;
	}

	public Object[] getElements(Object inputElement) {
		return getChildren(inputElement);
	}

	public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {

		if (newInput == null) {
			if (contentManager != null)
				contentManager.cancel(oldInput);
			return;
		}
		contentManager = new DeferredTreeContentManager(
				(AbstractTreeViewer) viewer);
	}

	public void dispose() {
		UserAdminUiPlugin.unregisterUserAdminListener(this);
	}

	public Object getParent(Object element) {
		return null;
	}

	private IRoleRootDescriptor[] getChildren(RoleRootsRegistry registry) {

		List<IRoleRootDescriptor> descriptors = registry.getRoleRoots();
		return descriptors.toArray(new IRoleRootDescriptor[descriptors.size()]);
	}

	private Role[] getChildren(IRoleRootDescriptor descriptor) {

		try {
			return userAdmin.getRoles(descriptor.getFilter());
		} catch (InvalidSyntaxException e) {
			return new Role[0];
		}
	}

	private Role[] getChildren(IRoleElement roleElement) {

		return roleElement.getChildren();
	}

	public void roleChanged(UserAdminEvent event) {
		/*
		 * final Role role = event.getRole(); IRoleElement adapter =
		 * adapt(event.getRole()); if (adapter == null) { return; }
		 * 
		 * if (event.getType() == UserAdminEvent.ROLE_CHANGED) {
		 * 
		 * for (final Group parent : adapter.getParents()) {
		 * viewer.getControl().getDisplay().asyncExec(new Runnable() {
		 * 
		 * public void run() { viewer.add(parent, role); } }); } } else if
		 * (event.getType() == UserAdminEvent.ROLE_REMOVED) {
		 * 
		 * viewer.getControl().getDisplay().asyncExec(new Runnable() {
		 * 
		 * public void run() {
		 * 
		 * viewer.remove(role); } });
		 * 
		 * } else {
		 * 
		 * Object selection =
		 * ((IStructuredSelection)viewer.getSelection()).getFirstElement(); if
		 * (selection != null) { viewer.refresh(selection); } }
		 */

		viewer.getControl().getDisplay().asyncExec(new Runnable() {

			public void run() {

				viewer.refresh();
			}
		});

	}

	public UserAdmin getUserAdmin() {
		return userAdmin;
	}

	public void setUserAdmin(UserAdmin userAdmin) {
		this.userAdmin = userAdmin;
	}

	public IAdapterManager getAdapterManager() {
		return adapterManager;
	}

	public void setAdapterManager(IAdapterManager adapterManager) {
		this.adapterManager = adapterManager;
	}

}
